﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Net.NetworkInformation;
using System.Text;
using System.Threading;
using System.Windows.Forms;
using QT.Windows.Shell;

namespace iNetScan
{
    public partial class Form1 : GlassForm
    {
        #region Attributes

        private static long StartIP = 0;
        private static long EndIP = 0;
        private static long IPCount = 0;
        private static long CurrentIP = 0;
        private static int IPThreadCount = 1;
        private static int IPCompleteCount = 0;
        private static string PortIP = "0.0.0.0";
        private static int StartPort = 0;
        private static int EndPort = 0;
        private static int PortCount = 0;
        private static int CurrentPort = 0;
        private static int PortThreadCount = 1;
        private static int PortCompleteCount = 0;

        private static bool IsIPRunning = false;
        private static bool IsIPPause = false;
        private static bool IsPortRunning = false;
        private static bool IsPortPause = false;

        private static Thread[] ScanIPThread;
        private static ManualResetEvent IPmre = new ManualResetEvent(true);
        private static Thread[] ScanPortThread;
        private static ManualResetEvent Portmre = new ManualResetEvent(true);
        private delegate void DeleGateIPListView(IPItem Item);
        private delegate void DeleGatePortListView(PortItem Item);
        private delegate void DeleGateSetStatusStrip(bool b, int index, string s);

        private IPConfig myIPs = new  IPConfig();

        #endregion

        #region Form

        public Form1()
        {
            InitializeComponent();
            SetIPBtnStart();
            SetIPBtnPause();
            SetPortBtnStart();
            SetPortBtnPause();
        }

        private void Form1_SizeChanged(object sender, EventArgs e)
        {
            if (this.WindowState == FormWindowState.Minimized)
            {
                this.notifyIcon1.Visible = true;
                this.Hide();
                this.ToolStripMenuItem_Main.Text = "显示主界面";
            }
        }

        private void Form1_Load(object sender, EventArgs e)
        {
            GetLocalIP();
            SetRect();
        }

        private void Form1_FormClosing(object sender, FormClosingEventArgs e)
        {
            e.Cancel = true;

            if (!(IsIPRunning || IsPortRunning)) e.Cancel = false;

            if (IsIPRunning)
            {
                if (MessageBox.Show("正在进行网络扫描，确认要退出吗？", "系统提示", MessageBoxButtons.OKCancel, MessageBoxIcon.Warning) == DialogResult.OK)
                {
                    Application.ExitThread();
                    return;
                }
            }            

            if (IsPortRunning)
            {
                if (MessageBox.Show("正在进行端口扫描，确认要退出吗？", "系统提示", MessageBoxButtons.OKCancel, MessageBoxIcon.Warning) == DialogResult.OK)
                {
                    Application.ExitThread();
                    return;
                }
            }
        }

        protected override void OnPaint(PaintEventArgs e)
        {
            base.OnPaint(e);
            this.statusStrip1.BackColor = AeroColor;
        }

        #endregion

        #region IPScan

        #region Button

        private void btnStartIPScan_Click(object sender, EventArgs e)
        {
            if (IsPortRunning)
            {
                MessageBox.Show("正在进行端口扫描，不能同时进行网络扫描");
                return;
            }

            if (!CheckIPInfo()) return;

            IPCount = EndIP - StartIP + 1;
            IPThreadCount = this.nudIPThreadCount.Value > IPCount ? (int)IPCount : (int)this.nudIPThreadCount.Value;
            IPCompleteCount = 0;
            IPmre.Set();
            this.pbScan.Maximum = (int)IPCount;
            
            if (IsIPRunning)
            {
                for (int i = 0; i < ScanIPThread.Length; i++)
                {
                    if (ScanIPThread[i].IsAlive) ScanIPThread[i].Abort();
                }
                IsIPRunning = false;
                IsIPPause = false;
                SetStatusStrip(true, IPCompleteCount, "扫描已终止");
            }
            else
            {
                this.lvIPScanResult.Items.Clear();
                ScanIPThread = new Thread[IPThreadCount];
                for (int i = 0; i < IPThreadCount; i++)
                {
                    ScanIPThread[i] = new Thread(new ThreadStart(ScanIP));
                    ScanIPThread[i].IsBackground = true;
                    ScanIPThread[i].Start();
                }
                IsIPRunning = true;
                IsIPPause = false;
            }

            SetIPBtnStart();
            SetIPBtnPause();
        }

        private void btnPauseIPScan_Click(object sender, EventArgs e)
        {
            if (IsIPPause)
            {
                IPmre.Set();
                IsIPPause = false;
            }
            else
            {
                IPmre.Reset();
                IsIPPause = true;
            }

            SetIPBtnPause();
        }

        #endregion

        #region ToolStripMenuItem

        private void ToolStripMenuItem_ExprotIPResultAll_Click(object sender, EventArgs e)
        {
            this.saveFileDialog1.ValidateNames = true;
            this.saveFileDialog1.Filter = "日志文件(*.log)|*.log|CSV文件(*.csv)|*.csv|Excel文件(*.xls)|*.xls";
            this.saveFileDialog1.FilterIndex = 1;
            this.saveFileDialog1.DefaultExt = "log";
            this.saveFileDialog1.FileName = "";
            this.saveFileDialog1.AddExtension = true;
            if (this.saveFileDialog1.ShowDialog() == DialogResult.Cancel)
            {
                return;
            }

            if (this.saveFileDialog1.FileName.EndsWith(".xls"))
            {
                if (Export.Export2Excel(lvIPScanResult, this.saveFileDialog1.FileName))
                {
                    MessageBox.Show("导出成功");
                }
                else
                {
                    MessageBox.Show("操作失败");
                    return;
                }
            }
            else
            {
                if (Export.Export2Txt(lvIPScanResult, this.saveFileDialog1.FileName))
                {
                    MessageBox.Show("导出成功");
                }
                else
                {
                    MessageBox.Show("操作失败");
                    return;
                }
            }
        }

        private void ToolStripMenuItem_ExprotIPResultSelect_Click(object sender, EventArgs e)
        {
            this.saveFileDialog1.ValidateNames = true;
            this.saveFileDialog1.Filter = "日志文件(*.log)|*.log|CSV文件(*.csv)|*.csv|Excel文件(*.xls)|*.xls";
            this.saveFileDialog1.FilterIndex = 1;
            this.saveFileDialog1.DefaultExt = "log";
            this.saveFileDialog1.FileName = "";
            this.saveFileDialog1.AddExtension = true;
            if (this.saveFileDialog1.ShowDialog() == DialogResult.Cancel)
            {
                return;
            }

            if (this.saveFileDialog1.FileName.EndsWith(".xls"))
            {
                if (Export.Export2Excel(lvIPScanResult, lvIPScanResult.SelectedItems, this.saveFileDialog1.FileName))
                {
                    MessageBox.Show("导出成功");
                }
                else
                {
                    MessageBox.Show("操作失败");
                    return;
                }
            }
            else
            {
                if (Export.Export2Txt(lvIPScanResult, lvIPScanResult.SelectedItems, this.saveFileDialog1.FileName))
                {
                    MessageBox.Show("导出成功");
                }
                else
                {
                    MessageBox.Show("操作失败");
                    return;
                }
            }
        }

        #endregion

        #region Method

        #region SetButton

        private void SetIPBtnStart()
        {
            if (IsIPRunning)
            {
                this.btnStartIPScan.Text = "终止";
            }
            else
            {
                this.btnStartIPScan.Text = "扫描";
            }
        }

        private void SetIPBtnPause()
        {
            if (IsIPRunning)
            {
                this.btnPauseIPScan.Enabled = true;
            }
            else
            {
                this.btnPauseIPScan.Enabled = false;
            }
            if (IsIPRunning && !IsIPPause)
            {
                this.btnPauseIPScan.Text = "暂停";
            }
            else
            {
                this.btnPauseIPScan.Text = "继续";
            }
        }

        #endregion

        #region Thread&DeleGate

        private void ScanIP()
        {
            long ip = GetIP();

            SetStatusStrip(true, IPCompleteCount, IPCompleteCount + "/{0}");
            while (ip != 0)
            {
                IPItem Item;
                try
                {
                    Item = Scan.IPScan(Scan.LongToIP(ip));
                    IPmre.WaitOne();
                    this.lvIPScanResult.Invoke(new DeleGateIPListView(AddIPItem), new object[] { Item });
                }
                catch (ThreadAbortException)
                {
                }

                IPCompleteCount++;
                SetStatusStrip(true, IPCompleteCount, IPCompleteCount + "/{0}");

                ip = GetIP();
            }

            if (GetIPThreadCount() == 0)
            {
                IsIPRunning = false;

                SetStatusStrip(true, IPCompleteCount, "扫描已完成");
                SetIPBtnStart();
                SetIPBtnPause();
            }
        }

        #endregion

        private bool CheckIPInfo()
        {
            if (this.tbIPStart.Text.Length == 0 && this.tbIPEnd.Text.Length == 0)
            {
                MessageBox.Show("请输入IP地址");
                return false;
            }
            if (this.tbIPStart.Text.Length == 0) this.tbIPStart.Text = this.tbIPEnd.Text;
            if (this.tbIPEnd.Text.Length == 0) this.tbIPEnd.Text = this.tbIPStart.Text;
            if (!QT.Net.NetWork.CheckIP(this.tbIPStart.Text) || !QT.Net.NetWork.CheckIP(this.tbIPEnd.Text))
            {
                MessageBox.Show("请输入合法的IP地址");
                return false;
            }
            if (QT.Net.NetWork.Compare(this.tbIPStart.Text, this.tbIPEnd.Text) > 0)
            {
                MessageBox.Show("结束IP必须大于或等于开始IP");
                return false;
            }
            if (this.nudIPThreadCount.Value > 100)
            {
                MessageBox.Show("系统错误，线程数不能大于最大限值");
                return false;
            }

            StartIP = Scan.IPToLong(this.tbIPStart.Text);
            EndIP = Scan.IPToLong(this.tbIPEnd.Text);
            CurrentIP = StartIP;

            return true;
        }

        private void AddIPItem(IPItem Item)
        {
            lock (this)
            {
                bool IsComplete = false;

                this.lvIPScanResult.BeginUpdate();
                ListViewItem newItem = new ListViewItem();
                newItem.SubItems[0].Text = "";
                newItem.SubItems.Add(Item.ip);
                newItem.SubItems.Add(Item.status);
                newItem.SubItems.Add(Item.mac);
                newItem.SubItems.Add(Item.hostname);

                for (int i = 0; i < this.lvIPScanResult.Items.Count; i++)
                {
                    if (!IsComplete && (QT.Net.NetWork.Compare(this.lvIPScanResult.Items[i].SubItems[1].Text, Item.ip) > 0))
                    {
                        this.lvIPScanResult.Items.Insert(i, newItem);
                        IsComplete = true;
                    }

                    this.lvIPScanResult.Items[i].SubItems[0].Text = (i + 1).ToString();
                }

                if (!IsComplete)
                {
                    this.lvIPScanResult.Items.Add(newItem);
                    this.lvIPScanResult.Items[this.lvIPScanResult.Items.Count - 1].SubItems[0].Text = this.lvIPScanResult.Items.Count.ToString();
                }

                this.lvIPScanResult.EndUpdate();
            }
        }

        private long GetIP()
        {
            long ip = 0;
            lock (this)
            {
                if (CurrentIP <= EndIP)
                {
                    ip = CurrentIP;
                    CurrentIP++;
                }
            }
            return ip;
        }

        private long GetIPThreadCount()
        {
            long i = 0;
            lock (this)
            {
                IPThreadCount--;
                i = IPThreadCount;
            }
            return i;
        }

        private void SetRect()
        {
            long ip_long = QT.Net.IP.IPToLong(myIPs.ip);
            long mask_long = QT.Net.IP.IPToLong(myIPs.mask);
            long netid_long = ip_long & mask_long;
            this.tbIPStart.Text = QT.Net.IP.LongToIP(netid_long + 1);
            this.tbIPEnd.Text = QT.Net.IP.LongToIP(netid_long + QT.Net.IP.IPToLong("255.255.255.255") - mask_long - 1);
        }

        #endregion

        #endregion

        #region PortScan

        #region Button

        private void btnStartPortScan_Click(object sender, EventArgs e)
        {
            if (IsIPRunning)
            {
                MessageBox.Show("正在进行网络扫描，不能同时进行端口扫描");
                return;
            }

            if (!CheckPortInfo()) return;

            PortIP = this.tbIP.Text;
            PortCount = EndPort - StartPort + 1;
            PortThreadCount = this.nudPortThreadCount.Value > PortCount ? PortCount : (int)this.nudPortThreadCount.Value;
            PortCompleteCount = 0;
            Portmre.Set();
            this.pbScan.Maximum = PortCount;
            this.pbScan.Value = 0;
            this.tsslStatus.Text = "0%";

            if (IsPortRunning)
            {
                for (int i = 0; i < ScanPortThread.Length; i++)
                {
                    if (ScanPortThread[i].IsAlive) ScanPortThread[i].Abort();
                }
                IsPortRunning = false;
                IsPortPause = false;
                SetStatusStrip(true, PortCompleteCount, "扫描已终止");
            }
            else
            {
                if (PortThreadCount > 100)
                {
                    if (MessageBox.Show("线程越多可能造成程序和电脑运行缓慢，确认要使用" + PortThreadCount + "个线程吗？", "系统提示", MessageBoxButtons.OKCancel, MessageBoxIcon.Warning) == DialogResult.Cancel) return;
                }

                this.lvPortScanResult.Items.Clear();
                ScanPortThread = new Thread[PortThreadCount];
                for (int i = 0; i < PortThreadCount; i++)
                {
                    ScanPortThread[i] = new Thread(new ThreadStart(ScanPort));
                    ScanPortThread[i].IsBackground = true;
                    ScanPortThread[i].Start();
                }
                IsPortRunning = true;
                IsPortPause = false;
            }

            SetPortBtnStart();
            SetPortBtnPause();
        }

        private void btnPausePortScan_Click(object sender, EventArgs e)
        {
            if (IsPortPause)
            {
                Portmre.Set();
                IsPortPause = false;
            }
            else
            {
                Portmre.Reset();
                IsPortPause = true;
            }

            SetPortBtnPause();
        }

        #endregion

        #region ToolStripMenuItem

        private void ToolStripMenuItem_ExprotPortResultAll_Click(object sender, EventArgs e)
        {
            this.saveFileDialog1.ValidateNames = true;
            this.saveFileDialog1.Filter = "日志文件(*.log)|*.log|CSV文件(*.csv)|*.csv|Excel文件(*.xls)|*.xls";
            this.saveFileDialog1.FilterIndex = 1;
            this.saveFileDialog1.DefaultExt = "log";
            this.saveFileDialog1.FileName = "";
            this.saveFileDialog1.AddExtension = true;
            if (this.saveFileDialog1.ShowDialog() == DialogResult.Cancel)
            {
                return;
            }

            if (this.saveFileDialog1.FileName.EndsWith(".xls"))
            {
                if (Export.Export2Excel(lvPortScanResult, this.saveFileDialog1.FileName))
                {
                    MessageBox.Show("导出成功");
                }
                else
                {
                    MessageBox.Show("操作失败");
                    return;
                }
            }
            else
            {
                if (Export.Export2Txt(lvPortScanResult, this.saveFileDialog1.FileName))
                {
                    MessageBox.Show("导出成功");
                }
                else
                {
                    MessageBox.Show("操作失败");
                    return;
                }
            }
        }

        private void ToolStripMenuItem_ExprotPortResultSelect_Click(object sender, EventArgs e)
        {

        }

        #endregion

        #region Method

        #region SetButton

        private void SetPortBtnStart()
        {
            if (IsPortRunning)
            {
                this.btnStartPortScan.Text = "终止";
            }
            else
            {
                this.btnStartPortScan.Text = "扫描";
            }
        }

        private void SetPortBtnPause()
        {
            if (IsPortRunning)
            {
                this.btnPausePortScan.Enabled = true;
            }
            else
            {
                this.btnPausePortScan.Enabled = false;
            }
            if (IsPortPause)
            {
                this.btnPausePortScan.Text = "继续";
            }
            else
            {
                this.btnPausePortScan.Text = "暂停";
            }
        }

        #endregion

        #region Thread&DeleGate

        private void ScanPort()
        {
            int port = GetPort();
            
            while (port != -1)
            {
                PortItem Item;
                try
                {
                    Item = Scan.PortScan(PortIP, port);
                    Portmre.WaitOne();
                    if (Item.status == "开放")
                    {
                        this.lvIPScanResult.Invoke(new DeleGatePortListView(AddPortItem), new object[] { Item });
                    }
                }
                catch (ThreadAbortException)
                {
                }

                PortCompleteCount++;
                Portmre.WaitOne();
                SetStatusStrip(true, PortCompleteCount, PortCompleteCount + "/{0}");

                port = GetPort();
            }

            if (GetPortThreadCount() == 0)
            {
                IsPortRunning = false;
                this.pbScan.Value = PortCount;
                SetStatusStrip(true, PortCompleteCount, "扫描已完成");
                SetPortBtnStart();
                SetPortBtnPause();
            }
        }

        #endregion

        private bool CheckPortInfo()
        {
            if (!QT.Net.NetWork.CheckIP(this.tbIP.Text))
            {
                MessageBox.Show("请输入合法的IP地址");
                return false;
            }
            if (this.tbStartPort.Text.Length == 0 && this.tbEndPort.Text.Length == 0)
            {
                MessageBox.Show("请输入端口号");
                return false;
            }
            if (this.tbStartPort.Text.Length == 0) this.tbStartPort.Text = this.tbEndPort.Text;
            if (this.tbEndPort.Text.Length == 0) this.tbEndPort.Text = this.tbStartPort.Text;
            if (!QT.Text.Match.IsNumeric(this.tbStartPort.Text) || !QT.Text.Match.IsNumeric(this.tbEndPort.Text))
            {
                MessageBox.Show("请输入合法的端口号");
                return false;
            }
            if (int.Parse(this.tbStartPort.Text) > 65535 || int.Parse(this.tbEndPort.Text) > 65535)
            {
                MessageBox.Show("合法端口号范围：0-65535");
                return false;
            }
            if (int.Parse(this.tbStartPort.Text) > int.Parse(this.tbEndPort.Text))
            {
                MessageBox.Show("起始端口必须小于等于结束端口");
                return false;
            }
            if (this.nudPortThreadCount.Value > this.nudPortThreadCount.Maximum)
            {
                MessageBox.Show("系统错误，线程数不能大于最大限值");
                return false;
            }

            StartPort = int.Parse(this.tbStartPort.Text);
            EndPort = int.Parse(this.tbEndPort.Text);
            CurrentPort = StartPort;

            return true;
        }

        private void AddPortItem(PortItem Item)
        {
            lock (this)
            {                
                bool IsComplete = false;

                this.lvPortScanResult.BeginUpdate();
                ListViewItem newItem = new ListViewItem();
                newItem.SubItems[0].Text = "";
                newItem.SubItems.Add(Item.port.ToString());
                newItem.SubItems.Add(Item.status);

                for (int i = 0; i < this.lvPortScanResult.Items.Count; i++)
                {
                    if (!IsComplete && (int.Parse(this.lvPortScanResult.Items[i].SubItems[1].Text) > Item.port))
                    {
                        this.lvPortScanResult.Items.Insert(i, newItem);
                        IsComplete = true;
                    }

                    this.lvPortScanResult.Items[i].SubItems[0].Text = (i + 1).ToString();
                }

                if (!IsComplete)
                {
                    this.lvPortScanResult.Items.Add(newItem);
                    this.lvPortScanResult.Items[this.lvPortScanResult.Items.Count - 1].SubItems[0].Text = this.lvPortScanResult.Items.Count.ToString();
                }

                this.lvPortScanResult.EndUpdate();
            }
        }

        private int GetPort()
        {
            int port = -1;
            lock (this)
            {
                if (CurrentPort <= EndPort)
                {
                    port = CurrentPort;
                    CurrentPort++;
                }
            }
            return port;
        }

        private int GetPortThreadCount()
        {
            int i = 0;
            lock (this)
            {
                PortThreadCount--;
                i = PortThreadCount;
            }
            return i;
        }

        private void GetLocalIP()
        {
            NetworkInterface[] NetworkInterfaces = NetworkInterface.GetAllNetworkInterfaces();
            foreach (NetworkInterface NetworkIntf in NetworkInterfaces)
            {
                if (NetworkIntf.OperationalStatus != OperationalStatus.Up) continue;

                if (NetworkIntf.NetworkInterfaceType == NetworkInterfaceType.Ethernet || NetworkIntf.NetworkInterfaceType == NetworkInterfaceType.Wireless80211)
                {
                    IPInterfaceProperties IPInterfaceProperties = NetworkIntf.GetIPProperties();

                    //获取本机IP地址信息，子网掩码信息
                    UnicastIPAddressInformationCollection UnicastIPAddressInformationCollections = IPInterfaceProperties.UnicastAddresses;
                    if (UnicastIPAddressInformationCollections.Count > 0)
                    {
                        for (int i = 0; i < UnicastIPAddressInformationCollections.Count; i++)
                        {
                            myIPs.ip = UnicastIPAddressInformationCollections[0].Address.ToString();
                            myIPs.mask = UnicastIPAddressInformationCollections[0].IPv4Mask == null ? "" : UnicastIPAddressInformationCollections[0].IPv4Mask.ToString();
                        }
                    }
                }
            }
        }

        #endregion

        #endregion 
    
        #region NotifyIcon

        private void ToolStripMenuItem_Main_Click(object sender, EventArgs e)
        {
            if (this.WindowState == FormWindowState.Normal)
            {
                this.WindowState = FormWindowState.Minimized;
                this.Hide();
                this.ToolStripMenuItem_Main.Text = "显示主界面";
            }
            else
            {
                this.Visible = true;
                this.WindowState = FormWindowState.Normal;
                this.ToolStripMenuItem_Main.Text = "隐藏主界面";
            }
        }

        private void ToolStripMenuItem_About_Click(object sender, EventArgs e)
        {
            MessageBox.Show("版权所有：QinTime.CN 2011-2012","关于我们",MessageBoxButtons.OK,MessageBoxIcon.Information);
        }

        private void ToolStripMenuItem_Exit_Click(object sender, EventArgs e)
        {
            this.Close();
        }

        private void notifyIcon1_MouseDoubleClick(object sender, MouseEventArgs e)
        {
            ToolStripMenuItem_Main_Click(new object(), new EventArgs());
        }

        #endregion

        #region Method

        private void SetStatusStrip(bool b,int index, string s)
        {
            if (this.InvokeRequired)
            {
                this.Invoke(new DeleGateSetStatusStrip(SetStatusStrip), new object[] { b, index, s });
            }
            else
            {
                this.pbScan.Value = index;
                this.tsslStatus.Text = string.Format(s, this.pbScan.Maximum.ToString());
                this.pbScan.Visible = b;
                this.tsslStatus.Visible = b;
            }
        }

        #endregion
    }

    public struct IPConfig
    {
        public string ip;
        public string mask;
    }
}
